package view;

import java.awt.Color;
import java.awt.DisplayMode;
import java.awt.Graphics2D;
import java.awt.Window;

public abstract class Core {
	/* How many frames will be drawn per second */
	private int fps = 60;
	/* Indicates that the game loop is running */
	private boolean running;
	/* The screen that will be used to draw upon */
	protected Screen screen;
	
	/** Initializes the game objects */
	public void init() {
		// Create screen
		this.screen = new Screen();
		
		// Set screen display mode
		DisplayMode displayMode = this.screen.getCurrentDisplayMode();
		this.screen.setFullScreen(displayMode);
		
		// Create JFrame
		Window window = this.screen.getFullScreenWindow();
		window.setBackground(Color.BLACK);
		window.setForeground(Color.WHITE);
		
		// By default the application is running
		running = true;
	}
	
	/** Run the game */
	public void run() {
		Thread loop = new Thread()
		{
			@Override
			public void run() {
				gameLoop();
			}
		};
		loop.start();
	}
	
	/** Stops the game */
	public void stop() {
		this.running = false;
		this.screen.restoreScreen();
		this.screen = null;
	}
	
	/** The game loop */
	public void gameLoop() {
		double delta = 1;
		long optimalTime = 1000000000 / this.fps;
		long startTime = System.nanoTime();
		long lastLoopTime = System.nanoTime();
		long updateTime = 0;
		Graphics2D g;
		
		while(running) {
			try
			{
				// Set the start time of the current loop
				startTime = System.nanoTime();
				
				// Check how much time has passed
				updateTime = startTime - lastLoopTime;
				
				// Set the start time of the previous loop
				lastLoopTime = startTime;
				
				// Time based updates will have to factor in this delta value
				delta = updateTime / ((double)optimalTime);
				  
				// Update the various game objects
				update(delta);
				  
				// Draw the various game objects
				g = this.screen.getGraphics();
				this.draw(g);
				this.screen.update();
				g.dispose();

				// Put thread to sleep
				Thread.sleep(20);
			}
			catch (Exception ex) {
				ex.printStackTrace();
			}
		}
	}
	
	/** Updates the various game objects */
	public abstract void update(double delta);
	
	/** Drawing of sprites */
	public abstract void draw(Graphics2D g);
}
